use super::config::{AccountConfig, Config, TaskConfig};
use super::day_counter::DayCounter;
use log::{info, warn};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;

#[derive(Clone)]
pub struct TaskManager {
    day_counters: Arc<RwLock<HashMap<String, DayCounter>>>,
}

impl TaskManager {
    pub fn new() -> Self {
        Self {
            day_counters: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    pub async fn can_execute_account(
        &self,
        account_key: &str,
        config: &Config,
        task_config: &TaskConfig,
        account: &AccountConfig,
    ) -> bool {
        let total_days = account.total_days
            .or(task_config.total_days)
            .or(config.schedule.total_days)
            .unwrap_or(0);

        if total_days == 0 {
            return true;
        }

        let mut counters = self.day_counters.write().await;
        let counter = counters
            .entry(account_key.to_string())
            .or_insert_with(|| DayCounter::new(total_days));

        let can_execute = counter.can_execute_today();

        if !can_execute && let Some(remaining) = counter.get_remaining_days() {
            if remaining == 0 {
                info!(
                    "Account {} has reached total_days limit ({}), will not execute anymore",
                    account_key,
                    counter.total_days
                );
            } else {
                info!(
                    "Account {} has {} days remaining",
                    account_key, remaining
                );
            }
        }

        can_execute
    }

    pub async fn record_account_execution(&self, account_key: &str) {
        let mut counters = self.day_counters.write().await;

        if let Some(counter) = counters.get_mut(account_key) {
            counter.record_execution();

            if let Some(remaining) = counter.get_remaining_days() {
                info!(
                    "Account {} execution recorded; {} days remaining",
                    account_key, remaining
                );
            }
        }
    }
    
    pub async fn update_next_execution_time(&self, account_key: &str, next_time: chrono::DateTime<chrono::Local>) {
        let mut counters = self.day_counters.write().await;
        
        if let Some(counter) = counters.get_mut(account_key) {
            counter.next_execution_time = Some(next_time);
        }
    }

    pub async fn get_all_progress(&self) -> HashMap<String, (u32, u32)> {
        let counters = self.day_counters.read().await;
        counters
            .iter()
            .map(|(name, counter)| (name.clone(), counter.get_progress()))
            .collect()
    }

    pub async fn save_all_counters(&self) -> Result<(), Box<dyn std::error::Error>> {
        let counters = self.day_counters.read().await;

        for (account_key, counter) in counters.iter() {
            // 解析任务名和账号昵称
            let parts: Vec<&str> = account_key.split(':').collect();
            if parts.len() == 2 {
                let task_name = parts[0];
                let nickname = parts[1];
                let safe_filename = Config::get_safe_filename(nickname);
                // 按任务名分目录存储: counters/任务名/账号_counter.json
                let file_path = format!("counters/{}/{}_counter.json", task_name, safe_filename);
                if let Err(e) = counter.save_to_file(&file_path) {
                    warn!(
                        "Failed to persist execution history for {}: {}",
                        account_key, e
                    );
                }
            } else {
                // 兼容旧格式
                let safe_filename = Config::get_safe_filename(account_key);
                let file_path = format!("{}_counter.json", safe_filename);
                if let Err(e) = counter.save_to_file(&file_path) {
                    warn!(
                        "Failed to persist execution history for {}: {}",
                        account_key, e
                    );
                }
            }
        }

        Ok(())
    }

    pub async fn load_all_counters(
        &mut self,
        config: &Config,
    ) -> Result<(), Box<dyn std::error::Error>> {
        let mut counters = self.day_counters.write().await;

        for task_config in &config.tasks {
            for account in &task_config.accounts {
                let total_days = account.total_days
                    .or(task_config.total_days)
                    .or(config.schedule.total_days)
                    .unwrap_or(0);

                let account_key = Config::get_account_key(&task_config.name, &account.nickname);
                let safe_filename = Config::get_safe_filename(&account.nickname);
                
                // 新路径: counters/任务名/账号_counter.json
                let new_file_path = format!("counters/{}/{}_counter.json", task_config.name, safe_filename);
                // 旧路径: 任务名_账号_counter.json (兼容)
                let old_file_path = format!("{}_counter.json", Config::get_safe_filename(&account_key));
                
                // 优先加载新路径,如果不存在则尝试旧路径
                let counter = if std::path::Path::new(&new_file_path).exists() {
                    DayCounter::from_file(&new_file_path, total_days)
                } else if std::path::Path::new(&old_file_path).exists() {
                    // 从旧路径加载并迁移到新路径
                    match DayCounter::from_file(&old_file_path, total_days) {
                        Ok(c) => {
                            info!("迁移counter文件: {} -> {}", old_file_path, new_file_path);
                            // 保存到新路径
                            if let Err(e) = c.save_to_file(&new_file_path) {
                                warn!("迁移失败: {}", e);
                            }
                            Ok(c)
                        }
                        Err(e) => Err(e)
                    }
                } else {
                    Ok(DayCounter::new(total_days))
                };
                
                match counter {
                    Ok(mut c) => {
                        // 更新剩余天数字段
                        c.remaining_days = c.get_remaining_days();
                        counters.insert(account_key.clone(), c);
                    }
                    Err(e) => {
                        warn!(
                            "Failed to load execution history for {}: {}",
                            account_key, e
                        );
                        counters.insert(account_key.clone(), DayCounter::new(total_days));
                    }
                }
            }
        }

        Ok(())
    }
}
